package io.jt808.proto.item;

import io.norland.buffer.AutoBuffer;

import java.util.HashMap;
import java.util.List;

public class ParameterItemUtil {
    private static HashMap<Integer, String> fieldTypeMap = new HashMap<>();

    static {
        fieldTypeMap.put(0x0001, "DWORD");
        fieldTypeMap.put(0x0002, "DWORD");
        fieldTypeMap.put(0x0003, "DWORD");
        fieldTypeMap.put(0x0004, "DWORD");
        fieldTypeMap.put(0x0005, "DWORD");
        fieldTypeMap.put(0x0006, "DWORD");
        fieldTypeMap.put(0x0007, "DWORD");
        fieldTypeMap.put(0x0010, "STRING");
        fieldTypeMap.put(0x0011, "STRING");
        fieldTypeMap.put(0x0012, "STRING");
        fieldTypeMap.put(0x0013, "STRING");
        fieldTypeMap.put(0x0014, "STRING");
        fieldTypeMap.put(0x0015, "STRING");
        fieldTypeMap.put(0x0016, "STRING");
        fieldTypeMap.put(0x0017, "STRING");
        fieldTypeMap.put(0x0018, "DWORD");
        fieldTypeMap.put(0x0019, "DWORD");
        fieldTypeMap.put(0x0020, "DWORD");
        fieldTypeMap.put(0x0021, "DWORD");
        fieldTypeMap.put(0x0022, "DWORD");
        fieldTypeMap.put(0x0027, "DWORD");
        fieldTypeMap.put(0x0028, "DWORD");
        fieldTypeMap.put(0x0029, "DWORD");
        fieldTypeMap.put(0x002C, "DWORD");
        fieldTypeMap.put(0x002D, "DWORD");
        fieldTypeMap.put(0x002E, "DWORD");
        fieldTypeMap.put(0x002F, "DWORD");
        fieldTypeMap.put(0x0030, "DWORD");
        fieldTypeMap.put(0x0031, "WORD");
        fieldTypeMap.put(0x0040, "STRING");
        fieldTypeMap.put(0x0041, "STRING");
        fieldTypeMap.put(0x0042, "STRING");
        fieldTypeMap.put(0x0043, "STRING");
        fieldTypeMap.put(0x0044, "STRING");
        fieldTypeMap.put(0x0045, "DWORD");
        fieldTypeMap.put(0x0046, "DWORD");
        fieldTypeMap.put(0x0047, "DWORD");
        fieldTypeMap.put(0x0048, "STRING");
        fieldTypeMap.put(0x0049, "STRING");
        fieldTypeMap.put(0x0050, "DWORD");
        fieldTypeMap.put(0x0051, "DWORD");
        fieldTypeMap.put(0x0052, "DWORD");
        fieldTypeMap.put(0x0053, "DWORD");
        fieldTypeMap.put(0x0054, "DWORD");
        fieldTypeMap.put(0x0055, "DWORD");
        fieldTypeMap.put(0x0056, "DWORD");
        fieldTypeMap.put(0x0057, "DWORD");
        fieldTypeMap.put(0x0058, "DWORD");
        fieldTypeMap.put(0x0059, "DWORD");
        fieldTypeMap.put(0x005A, "DWORD");
        fieldTypeMap.put(0x0070, "DWORD");
        fieldTypeMap.put(0x0071, "DWORD");
        fieldTypeMap.put(0x0072, "DWORD");
        fieldTypeMap.put(0x0073, "DWORD");
        fieldTypeMap.put(0x0074, "DWORD");
        fieldTypeMap.put(0x0080, "DWORD");
        fieldTypeMap.put(0x0081, "WORD");
        fieldTypeMap.put(0x0082, "WORD");
        fieldTypeMap.put(0x0083, "STRING");
        fieldTypeMap.put(0x0084, "BYTE");
        fieldTypeMap.put(0x0094, "BYTE");
        fieldTypeMap.put(0x0095, "DWORD");
        fieldTypeMap.put(0x0100, "DWORD");
        fieldTypeMap.put(0x0101, "DWORD");
        fieldTypeMap.put(0x0102, "DWORD");
        fieldTypeMap.put(0x0103, "BYTE");
        fieldTypeMap.put(0x0104, "BYTE");
        fieldTypeMap.put(0x0105, "STRING");
        fieldTypeMap.put(0x0106, "DWORD");
        fieldTypeMap.put(0x0107, "DWORD");
        fieldTypeMap.put(0x0108, "DWORD");
        fieldTypeMap.put(0x0109, "DWORD");
        fieldTypeMap.put(0x010a, "DWORD");
        fieldTypeMap.put(0x010b, "DWORD");
        fieldTypeMap.put(0x010c, "BYTE");
        fieldTypeMap.put(0x010d, "WORD");
        fieldTypeMap.put(0x010e, "WORD");
        fieldTypeMap.put(0x010f, "WORD");
        fieldTypeMap.put(0xf000, "BYTE+N");
        fieldTypeMap.put(0xf001, "BYTE+N");
        fieldTypeMap.put(0xf002, "BYTE+N");
        fieldTypeMap.put(0xf003, "BYTE+N");
        fieldTypeMap.put(0xf004, "BYTE+N");
    }

    public static void readParamByteFromBuf(AutoBuffer buff, List<ParameterItem> parameters) {
        while (buff.isReadable()) {
            ParameterItem item = new ParameterItem();
            item.setParameterId(buff.readInt());
//            String hex=Integer.toHexString(item.getParameterId());
            item.setParameterLength(buff.readByte());
            String fieldType = fieldTypeMap.get(item.getParameterId());
            switch (fieldType) {
                case "BYTE+N":
                    readByteN(buff, item);
                    break;
                case "BYTE":// 参数值为byte类型
                    item.setParameterValue(buff.readByte());
                    break;
                case "WORD":// 参数值为ushort类型
                    item.setParameterValue(buff.readShort());
                    break;
                case "DWORD":// 参数值为uint类型
                    item.setParameterValue(buff.readInt());
                    break;
                default://STRING
                    item.setParameterValue(buff.readString());
                    break;
            }
            parameters.add(item);
        }
    }

    private static void readByteN(AutoBuffer buff, ParameterItem item) {
        switch (item.getParameterLength()) {
            case 0:
                break;
            case 1:
                item.setParameterValue(buff.readByte());
                break;
            case 2:
                item.setParameterValue(buff.readShort());
                break;
            case 3:
                int value = (buff.readByte() & 0xFF) << 16 |
                        (buff.readByte() & 0xFF) << 8 |
                        buff.readByte() & 0xFF;
                item.setParameterValue(value);
                break;
            case 4:
                item.setParameterValue(buff.readInt());
                break;
            default:
                byte[] bytes = new byte[item.getParameterLength()];
                for (int i = 0; i < item.getParameterLength(); i++) {
                    bytes[i] = buff.readByte();
                }
                item.setParameterValue(bytes);
                break;
        }
    }

    public static void writeParamByte(AutoBuffer buff, List<ParameterItem> parameters) {
        for (ParameterItem item : parameters) {
            buff.writeInt(item.getParameterId());
            buff.writeByte(item.getParameterLength());

            String fieldType = fieldTypeMap.get(item.getParameterId());
            switch (fieldType) {
                case "BYTE+N":
                    writeByteN(buff, item.getParameterLength(), item.getParameterValue());
                    break;
                case "BYTE":
                    buff.writeByte((Byte) item.getParameterValue());
                    break;
                case "WORD":
                    buff.writeShort((Short) item.getParameterValue());
                    break;
                case "DWORD":
                    buff.writeInt((Integer) item.getParameterValue());
                    break;
                default://STRING
                    buff.writeString((String) item.getParameterValue());
                    break;
            }
        }
    }

    private static void writeByteN(AutoBuffer buff, int itemLength, Object paramValue) {
        switch (itemLength) {
            case 0:
                break;
            case 1:
                buff.writeByte((Byte) paramValue);
                break;
            case 2:
                buff.writeShort((Short) paramValue);
                break;
            case 3:
                int value = (int) paramValue;
                byte[] bytes = new byte[3];
                bytes[0] = (byte) (value >> 16 & 0xFF);
                bytes[1] = (byte) (value >> 8 & 0xFF);
                bytes[2] = (byte) (value & 0xFF);
                buff.writeBytes(bytes);
                break;
            case 4:
                buff.writeInt((Integer) paramValue);
                break;
            default:
                byte[] bytez = (byte[]) paramValue;
                for (byte b : bytez)
                    buff.writeByte(b);
                break;
        }
    }
}
